package database

import (
	"errors"
	"fmt"
)

// 预定义的数据库错误类型
var (
	ErrConnectionFailed   = errors.New("数据库连接失败")
	ErrQueryTimeout      = errors.New("查询超时")
	ErrInvalidQuery      = errors.New("无效的查询语句")
	ErrTableNotFound     = errors.New("表不存在")
	ErrInvalidTableName  = errors.New("无效的表名")
	ErrConnectionClosed  = errors.New("数据库连接已关闭")
	ErrTooManyConnections = errors.New("连接数过多")
	ErrQueryCancelled    = errors.New("查询被取消")
)

// DatabaseError 数据库错误包装器
type DatabaseError struct {
	Operation string // 操作类型
	Table     string // 相关表名（可选）
	Err       error  // 原始错误
}

// Error 实现error接口
func (e *DatabaseError) Error() string {
	if e.Table != "" {
		return fmt.Sprintf("数据库操作失败 [%s] 表[%s]: %v", e.Operation, e.Table, e.Err)
	}
	return fmt.Sprintf("数据库操作失败 [%s]: %v", e.Operation, e.Err)
}

// Unwrap 返回原始错误
func (e *DatabaseError) Unwrap() error {
	return e.Err
}

// NewDatabaseError 创建数据库错误
func NewDatabaseError(operation string, err error) *DatabaseError {
	return &DatabaseError{
		Operation: operation,
		Err:       err,
	}
}

// NewTableError 创建表相关错误
func NewTableError(operation, table string, err error) *DatabaseError {
	return &DatabaseError{
		Operation: operation,
		Table:     table,
		Err:       err,
	}
}

// NewQueryError 创建查询错误
func NewQueryError(query string, err error) *DatabaseError {
	return &DatabaseError{
		Operation: fmt.Sprintf("query: %s", query),
		Err:       err,
	}
}

// 错误检查函数
func IsConnectionError(err error) bool {
	var dbErr *DatabaseError
	if errors.As(err, &dbErr) {
		return errors.Is(dbErr.Err, ErrConnectionFailed) || 
			   errors.Is(dbErr.Err, ErrConnectionClosed) ||
			   errors.Is(dbErr.Err, ErrTooManyConnections)
	}
	return errors.Is(err, ErrConnectionFailed) || 
		   errors.Is(err, ErrConnectionClosed) ||
		   errors.Is(err, ErrTooManyConnections)
}

// IsTimeoutError 检查是否为超时错误
func IsTimeoutError(err error) bool {
	var dbErr *DatabaseError
	if errors.As(err, &dbErr) {
		return errors.Is(dbErr.Err, ErrQueryTimeout)
	}
	return errors.Is(err, ErrQueryTimeout)
}

// IsTableError 检查是否为表相关错误
func IsTableError(err error) bool {
	var dbErr *DatabaseError
	if errors.As(err, &dbErr) {
		return errors.Is(dbErr.Err, ErrTableNotFound) || 
			   errors.Is(dbErr.Err, ErrInvalidTableName)
	}
	return errors.Is(err, ErrTableNotFound) || 
		   errors.Is(err, ErrInvalidTableName)
}

// IsQueryError 检查是否为查询错误
func IsQueryError(err error) bool {
	var dbErr *DatabaseError
	if errors.As(err, &dbErr) {
		return errors.Is(dbErr.Err, ErrInvalidQuery) || 
			   errors.Is(dbErr.Err, ErrQueryCancelled)
	}
	return errors.Is(err, ErrInvalidQuery) || 
		   errors.Is(err, ErrQueryCancelled)
}